package control;

import control.Master;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import model.UserInfo;
import model.UserInfoClearText;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Ragnarokr
 */
public class SlaveService implements Runnable {

    protected Socket socket;

    /**
     * Get the value of socket
     *
     * @return the value of socket
     */
    public Socket getSocket() {
        return socket;
    }

    /**
     * Set the value of socket
     *
     * @param socket new value of socket
     */
    public void setSocket(Socket socket) {
        this.socket = socket;
    }
    protected Master masterController;

    /**
     * Get the value of masterController
     *
     * @return the value of masterController
     */
    public Master getMasterController() {
        return masterController;
    }

    /**
     * Set the value of masterController
     *
     * @param masterController new value of masterController
     */
    public void setMasterController(Master masterController) {
        this.masterController = masterController;
    }

    /**
     * Starts the slave service handler which controls the connection to a slave
     */
    public void run() {
        try {
            while (true) {
                sendDictionaryPart(getMasterController().getCurrentDPart());
                recieveResults();
                if (!getMasterController().moreUsersToBeFound() || !getMasterController().moreInDictionary()) {
                    getSocket().shutdownInput();
                    getSocket().shutdownOutput();
                    getSocket().close();
                    break;
                }
            }
        } catch (IOException ex) {
            Logger.getLogger(SlaveService.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(SlaveService.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Creates an instance of the class SlaveServiceHandler
     * @param socket The socket connection to the slave
     * @param masterController The masterController that initiated the slave connection
     */
    public SlaveService(Socket socket, Master masterController) {
        this.socket = socket;
        this.masterController = masterController;
    }

    /**
     * Sends user info to the slave
     * @param userInfo The user info to be sent to the slave
     * @throws IOException
     */
    public void sendUserInfo(List<UserInfo> userInfo) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(getSocket().getOutputStream());
        oos.writeObject(userInfo);
    }

    /**
     * Sends a dictionary chunk to the slave
     * @param dPart The dictionary chunk to be sent to the slave
     * @throws IOException
     */
    public void sendDictionaryPart(List<String> dPart) throws IOException {
        ArrayList<String> al = (ArrayList<String>) dPart;
        setDPart(dPart);
        ObjectOutputStream oos = new ObjectOutputStream(getSocket().getOutputStream());
        oos.writeObject(al);
    }
    protected List<String> dPart;

    /**
     * Get the value of dPart
     *
     * @return the value of dPart
     */
    public List<String> getDPart() {
        return dPart;
    }

    /**
     * Set the value of dPart
     *
     * @param dPart new value of dPart
     */
    public void setDPart(List<String> dPart) {
        this.dPart = dPart;
    }

    /**
     * Retrieves the results from the slave and sends it to the masterController
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private void recieveResults() throws IOException, ClassNotFoundException {
        try {
            ObjectInputStream oin = new ObjectInputStream(getSocket().getInputStream());
            Object o = oin.readObject();
            List<UserInfoClearText> results = null;
            if (o instanceof List) {
                results = (List<UserInfoClearText>) o;
            }
            getMasterController().handleResults(results);
        } catch (EOFException ex) {
            System.err.println("EOF exception in recieve results");
            getMasterController().getDParts().add(getDPart());
        }
    }
}
